// #include<iostream>
// #include<pthread.h>
// #include<cassert>
// #include<string>
#include <unistd.h>
#include "Thread.hpp"

// // 定义一个全局变量。
// int g_val = 10000;
// // 总票数是10000

// pthread_mutex_t mutex ;
// //pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

// // 抢票函数
// void *fun(void *argc)
// {
//     std::string str = (char *)argc;
//     while (true)
//     {
//         // 判断当前是否有票
//         pthread_mutex_lock(&mutex);
//         if (g_val > 0)
//         {
//             usleep(100);
//             std::cout << str << " runing...."
//                       << "当前正在进行抢票！！ "
//                       << " g_val:" << g_val << std::endl;
//             g_val--;
//             pthread_mutex_unlock(&mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&mutex);
//             break;
//         }
//         usleep(100);
//     }
//     return nullptr;
// }

// int main()
// {
//     // 假如有五个人在同时抢票。
//     pthread_mutex_init(&mutex, nullptr);
//     Thread tp1(fun, 1, (void *)"thread-1");
//     Thread tp2(fun, 2, (void *)"thread-2");
//     Thread tp3(fun, 3, (void *)"thread-3");
//     Thread tp4(fun, 4, (void *)"thread-4");
//     Thread tp5(fun, 5, (void *)"thread-5");

//     tp1.join();
//     tp2.join();
//     tp3.join();
//     tp4.join();
//     tp5.join();

//     // 这是一个测试代码，目的是为了让我们测出抢票，最后把票抢到负数，出现票多卖的问题。
//     // 就需要尽可以的让多个线程交叉执行。
//     // 本质是让调度器频繁调度，线程频繁切换。 //线程发生线程切换情况：
//     // 1.时间片到了。
//     // 2.来了更高优先级的线程。
//     // 3.线程等待的时候。
//     // 线程在内核态返回用户态的时候，OS会对调度状态进行检测，如果满足上述条件，直接发送线程切换。

//     return 0;
// }

// // 定义一个全局变量。
// int g_val = 10000;
// // 总票数是10000

// pthread_mutex_t mutex;
// // pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

// // 抢票函数
// void *fun(void *argc)
// {
//     std::string str = (char *)argc;
//     while (true)
//     {
//         // 判断当前是否有票
//         pthread_mutex_lock(&mutex);
//         if (g_val > 0)
//         {
//             usleep(100);
//             std::cout << str << " runing...."
//                       << "当前正在进行抢票！！ "
//                       << " g_val:" << g_val << std::endl;
//             g_val--;
//             pthread_mutex_unlock(&mutex);
//         }
//         else
//         {
//             pthread_mutex_unlock(&mutex);
//             break;
//         }
//         // pthread_mutex_unlock(&mutex);//写这里不对。
//         usleep(100);
//         // 加锁之后每个线程是串行的访问此临界区的。所以程序会变慢一点点。
//         // 注意这里需要等待一下，不会都是一个线程会一直抢票，其他线程会出现饥饿状态。
//         // 线程互斥只是规定了线程互斥访问，没有规定谁优先执行。就会出现竞争，就会出现饥饿线程。
//     }
//     return nullptr;
// }

// int main()
// {
//     // 假如有五个人在同时抢票。
//     pthread_mutex_init(&mutex, nullptr);
//     Thread tp1(fun, 1, (void *)"thread-1");
//     Thread tp2(fun, 2, (void *)"thread-2");
//     Thread tp3(fun, 3, (void *)"thread-3");
//     Thread tp4(fun, 4, (void *)"thread-4");
//     Thread tp5(fun, 5, (void *)"thread-5");

//     tp1.join();
//     tp2.join();
//     tp3.join();
//     tp4.join();
//     tp5.join();

//     return 0;
// }

#include "Mutex.hpp"
// 定义一个全局变量。
int g_val = 10000;
// 总票数是10000
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
// 只有全局互斥量和静态互斥量才能这样初始化

// 抢票函数
void *fun(void *argc)
{
    std::string str = (char *)argc;
    while (true)
    {
        // 判断当前是否有票
        {
            LockGuard lockguard(&mutex);//RAII风格的加锁
            //可以是用花括号{ }来控制临界区范围。
            if (g_val > 0)
            {
                usleep(100);
                std::cout << str << " runing...."
                          << "当前正在进行抢票！！ "
                          << " g_val:" << g_val << std::endl;
                g_val--;
            }
            else
            {
                break;
            }
        }
        usleep(100);
    }
    return nullptr;
}

int main()
{
    // 假如有五个人在同时抢票。
    Thread tp1(fun, 1, (void *)"thread-1");
    Thread tp2(fun, 2, (void *)"thread-2");
    Thread tp3(fun, 3, (void *)"thread-3");
    Thread tp4(fun, 4, (void *)"thread-4");
    Thread tp5(fun, 5, (void *)"thread-5");

    tp1.join();
    tp2.join();
    tp3.join();
    tp4.join();
    tp5.join();

    return 0;
}



